From c5ad7bd0fa0b6d8248cf2c41bb5671c259f5a56d Mon Sep 17 00:00:00 2001 From: "mafetter@fleming.research" Date: Wed, 16 Mar 2005 01:17:37 +0000 Subject: [PATCH] bitkeeper revision 1.1236.32.9 (42378931ytaSYjOpR6-Ss599yO6Zjg) Added unshadowing of L2s that contain entries which are both not present and non-zero. This is a hack, but ought to work OK for linux domains. Signed-off-by: michael.fetterman@cl.cam.ac.uk --- xen/arch/x86/shadow.c | 24 +++++++++++++++++++----- xen/include/asm-x86/shadow.h | 9 +++++---- xen/include/xen/perfc_defn.h | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 8208c4147f..67aea9110e 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -299,8 +299,6 @@ free_shadow_hl2_table(struct domain *d, unsigned long smfn) static void inline free_shadow_l2_table(struct domain *d, unsigned long smfn) { - printk("free_shadow_l2_table(smfn=%p)\n", smfn); - unsigned long *pl2e = map_domain_mem(smfn << PAGE_SHIFT); int i, external = shadow_mode_external(d); @@ -1666,6 +1664,7 @@ static int resync_all(struct domain *d, u32 stype) unsigned long smfn; unsigned long *guest, *shadow, *snapshot; int need_flush = 0, external = shadow_mode_external(d); + int unshadow; ASSERT(spin_is_locked(&d->arch.shadow_lock)); @@ -1686,6 +1685,7 @@ static int resync_all(struct domain *d, u32 stype) guest = map_domain_mem(entry->gmfn << PAGE_SHIFT); snapshot = map_domain_mem(entry->snapshot_mfn << PAGE_SHIFT); shadow = map_domain_mem(smfn << PAGE_SHIFT); + unshadow = 0; switch ( stype ) { case PGT_l1_shadow: @@ -1719,6 +1719,16 @@ static int resync_all(struct domain *d, u32 stype) // // snapshot[i] = new_pde; } + + // XXX - This hack works for linux guests. + // Need a better solution long term. + if ( !(new_pde & _PAGE_PRESENT) && unlikely(new_pde != 0) && + (frame_table[smfn].u.inuse.type_info & PGT_pinned) && + !unshadow ) + { + perfc_incrc(unshadow_l2_count); + unshadow = 1; + } } break; default: @@ -1729,6 +1739,9 @@ static int resync_all(struct domain *d, u32 stype) unmap_domain_mem(shadow); unmap_domain_mem(snapshot); unmap_domain_mem(guest); + + if ( unlikely(unshadow) ) + shadow_unpin(smfn); } return need_flush; @@ -1919,7 +1932,7 @@ void __update_pagetables(struct exec_domain *ed) struct domain *d = ed->domain; unsigned long gmfn = pagetable_val(ed->arch.guest_table) >> PAGE_SHIFT; unsigned long gpfn = __mfn_to_gpfn(d, gmfn); - unsigned long smfn, hl2mfn; + unsigned long smfn, hl2mfn, old_smfn; int max_mode = ( shadow_mode_external(d) ? SHM_external : shadow_mode_translate(d) ? SHM_translate @@ -1946,9 +1959,10 @@ void __update_pagetables(struct exec_domain *ed) smfn = shadow_l2_table(d, gpfn, gmfn); if ( !get_shadow_ref(smfn) ) BUG(); - if ( pagetable_val(ed->arch.shadow_table) ) - put_shadow_ref(pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT); + old_smfn = pagetable_val(ed->arch.shadow_table) >> PAGE_SHIFT; ed->arch.shadow_table = mk_pagetable(smfn << PAGE_SHIFT); + if ( old_smfn ) + put_shadow_ref(old_smfn); SH_VVLOG("0: __update_pagetables(gmfn=%p, smfn=%p)", gmfn, smfn); diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 6cb1dd4bd2..a17c601611 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -651,7 +651,7 @@ validate_pte_change( static int inline validate_pde_change( struct domain *d, - unsigned long new_pde, + unsigned long new_gpde, unsigned long *shadow_pde_p) { unsigned long old_spde, new_spde; @@ -659,11 +659,12 @@ validate_pde_change( perfc_incrc(validate_pde_calls); old_spde = *shadow_pde_p; - l2pde_propagate_from_guest(d, &new_pde, &new_spde); + l2pde_propagate_from_guest(d, &new_gpde, &new_spde); - // XXX Shouldn't we supposed to propagate the new_pde to the guest? + // XXX Shouldn't we propagate the new_gpde to the guest? + // And then mark the guest's L2 page as dirty? - // only do the ref counting if something important changed. + // Only do the ref counting if something important changed. // if ( ((old_spde | new_spde) & _PAGE_PRESENT) && ((old_spde ^ new_spde) & (PAGE_MASK | _PAGE_PRESENT)) ) diff --git a/xen/include/xen/perfc_defn.h b/xen/include/xen/perfc_defn.h index e4b506171b..058265c416 100644 --- a/xen/include/xen/perfc_defn.h +++ b/xen/include/xen/perfc_defn.h @@ -30,6 +30,7 @@ PERFCOUNTER_CPU( shadow_set_l1e_force_map, "shadow_set_l1e forced to map l1" ) PERFCOUNTER_CPU( shadow_set_l1e_unlinked, "shadow_set_l1e found unlinked l1" ) PERFCOUNTER_CPU( shadow_set_l1e_fail, "shadow_set_l1e failed (no sl1)" ) PERFCOUNTER_CPU( shadow_invlpg_faults, "shadow_invlpg's get_user faulted") +PERFCOUNTER_CPU( unshadow_l2_count, "unpinned L2 count") /* STATUS counters do not reset when 'P' is hit */ -- 2.30.2